/*
 * @Author: xiaosihan 
 * @Date: 2024-11-28 09:20:48 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2025-01-20 18:09:50
 */
import { FrontSide, Material, MeshLambertMaterial, MeshPhongMaterial, MeshStandardMaterial } from "three";

// 把非stander的材质转成stander材质
export default function toStanderMaterial<T extends Material | Material[]>(material: T): T {
  if (material instanceof MeshPhongMaterial) {
    const { shininess, normalMap, normalScale, bumpMap, emissiveMap, emissive } = material as MeshPhongMaterial;

    // 创建一个新的标准材质
    const newMaterial = new MeshStandardMaterial();
    // 赋值参数到新的材质上去
    for (let i in newMaterial) {
      if (!['type'].includes(i) && newMaterial.hasOwnProperty(i) && material.hasOwnProperty(i)) {
        //@ts-ignore
        newMaterial[i] = material[i];
      }
    }
    // 参数微调
    emissiveMap && emissive.set(1, 1, 1);
    newMaterial.setValues({
      normalMap: (normalScale.length() <= 0.2 ? null : normalMap) || bumpMap,
      metalness: 0,
      //TODO 还需要考虑到反射颜色的对金属性参数的印象 specular
      roughness: Math.max(0.2, 1 - shininess / 100),
      emissiveMap,
      emissive,
      side: FrontSide,
    });
    return newMaterial as Material as T;
  } else if (material instanceof MeshLambertMaterial) {
    const { normalMap, normalScale, bumpMap, emissiveMap, emissive } = material as MeshLambertMaterial;
    // 创建一个新的标准材质
    const newMaterial = new MeshStandardMaterial();
    // 赋值参数到新的材质上去
    for (let i in newMaterial) {
      if (!['type'].includes(i) && newMaterial.hasOwnProperty(i) && material.hasOwnProperty(i)) {
        //@ts-ignore
        newMaterial[i] = material[i];
      }
    }
    // 参数微调
    emissiveMap && emissive.set(1, 1, 1);
    newMaterial.setValues({
      normalMap: (normalScale.length() <= 0.2 ? null : normalMap) || bumpMap,
      metalness: 0,
      roughness: 1,
      emissiveMap,
      emissive,
      side: FrontSide,
    });
    return newMaterial as Material as T;
  } else if (material instanceof Array) {
    return material.map((m) => toStanderMaterial(m)) as Material[] as T;
  } else {
    material.side = FrontSide;
    return material as T;
  }
}
